import splToken from "@/libs/spl-token.js";
import solanaWeb3 from "@/libs/solana.js";
const {
	SystemProgram,
	Transaction,
	Connection,
	PublicKey,
	LAMPORTS_PER_SOL
} = solanaWeb3;
// alert(splToken.splToken.Token)
const {
	createApproveInstruction,
	createTransferInstruction,
	findAssociatedTokenAddress,
	AccountLayout,
	createAccount,
	createAssociatedTokenAccount,
	getAccount,
	getTokenAccountsByOwner,
	getOrCreateAssociatedTokenAccount,
	Token,
	TOKEN_PROGRAM_ID
} = splToken.splToken;
window.solana_mainnet = "https://solana-mainnet.phantom.tech"
window.connection = new Connection(solana_mainnet);

export default {
	async search_tx_status(tx_arr) {
		let that = this;
		// https://public-api.solscan.io/transaction/
		return new Promise(succ => {
			let run_count = 1;
			let si = setInterval(() => {
				run_count = run_count + 1;
				if(run_count >= 25){
					clearInterval(si);
					succ(true);
					return;
				}
				connection.getSignatureStatuses(tx_arr).then(res => {
					console.log("轮询获取交易状态", res);
					let len = tx_arr.length;
					let confrimed = [];
					let value = res.value;
					for (let i = 0; i < len; i++) {
						let curr = value[i];
						console.log(curr);
						if (curr) {
							console.log(curr.confirmationStatus);
							// confirmed / finalized && curr.confirmations >= 10
							if (curr.confirmationStatus == "confirmed" ) {
								if(curr.confirmations && curr.confirmations >= 4){
									confrimed.push(true);
								}
								
							}
							// console.log("我的交易",sign,res.value[0].confirmationStatus);
						}
					}
					console.log("交易数量", len, "确认数量", confrimed.length);
					if (confrimed.length == len) {
						clearInterval(si);
						succ(true);
					}
					// console.log("我的交易",sign,res.value[0].confirmationStatus);
				});
			}, 1000)
		})
	},
	async send_token() {
		let that = this;
		let solana_pubkey = await that.connect_solana();
		let txid = await that.transfer_solana_token({
			from: solana_pubkey,
			// to:"E4arVojqSTsrFQHbpy9aF5qNtMvoKKPM3hj8j6eYfzuQ",
			to: "Exrb1iprXcRZcjyyaCj62onZnEbkJR6QLP6EdLMGw1Mx",
			number: 0.01,
			token: {
				format: 9,
				mint: "DkPn7EwX229HDWL9suY9o2GN6iov2pMpXhvujkUjav6A",
				name: "Solrs"
			}
		});
		console.log("交易数九", txid);
	},
	 get_balance(mint, format) {
		let that = this;
		console.log("查询余额",'合约地址',mint);
		return new Promise(async succ => {
			let my_key = window.solana.publicKey.toBase58();
			console.log("我的key",my_key);
			if (mint) {
				let account = await that.get_solana_account(my_key, mint);
				console.log("account", account);
				if (account) {
					let amount = account.amount;
					amount = parseFloat(Math.floor(amount / Math.pow(10, format) * 10000) / 10000);
					succ('' + amount)
					return;
				} else {
					succ('0');
					return;
				}
			} else {
				connection.getBalance(new PublicKey(my_key)).then(balance => {
					window.parent.console.info('query sol balance ', balance)  
					// balance = balance / Math.pow(10, format);
					
					balance = parseFloat(Math.floor(balance / Math.pow(10, format) * 10000) / 10000);
					succ('' + balance)
				}).catch(e => {
					window.parent.console.error('query sol balance error', e)
					succ('0');
				});
			}
		})

	},
	async connect_solana() {
		let that = this;
		return new Promise(succ => {
			let timer_count = 0;
			let timer_task = setInterval(async function() {
				if (window.solana || (window.bitkeep && window.bitkeep.solana)) {
					if (window.bitkeep) {
						window.solana = window.bitkeep.solana
					}
					await window.solana.connect();
					clearInterval(timer_task);
					console.log(window.solana);
					succ(window.solana.publicKey)
				}
				if (timer_count >= 20) {
					clearInterval(timer_task);
					succ('')
					// alert('请连接solana钱包');
				}
				timer_count++;

			}, 200)
		})
	},
	get_solana_account(pubkey, mint) {
		let that = this;
		return new Promise(async succ => {
			try {
				if (typeof pubkey == "string") {
					pubkey = new PublicKey(pubkey);
				}
				if (typeof mint == "string") {
					mint = new PublicKey(mint);
				}
				if (!connection) {
					connection = new Connection(solana_mainnet)
				}
				let token_instance = new Token(connection, mint, TOKEN_PROGRAM_ID, new PublicKey(window
					.solana.publicKey.toBase58()));
				console.log("connection", connection);
				let token_account = await token_instance.getOrCreateAssociatedAccountInfo(pubkey).catch(
					err => {
						if (err.toString() == "Error: Failed to find account") {
							uni.$emit("account_not_find", {
								address: pubkey,
								msg: err.toString(),
								mint: mint

							})
							// that.main.watch_error('account_not_find',{
							// 	address:pubkey,
							// 	msg:err.toString()
							// })
							succ('');


							// alert("找不到代币账户");
						}
						console.log(err.toString());
					})
				if (!token_account) {
					succ('');
					return;
				}
				succ(token_account)

			} catch (e) {
				if (e.toString() == "")
					console.error(e.toString());
				succ('');
				//TODO handle the exception
			}
		})
	},
	//授权
	async approve(mint, to, number) {
		let that = this;
		let from = new PublicKey(window.solana.publicKey.toBase58());
		return new Promise(async succ => {
			if (mint) {
				try{
					mint = new PublicKey(mint);
					//获取发送方的代币账户
					from = await that.get_solana_account(from, mint);
					if (!from) {
						return;
					}
					console.log("from", from);
					//获取接收方的代币账户
					to = await that.get_solana_account(to, mint);
					if (!to) {
						return;
					}
					console.log("to", to);
					if (!connection) {
						//连接solana网络
						connection = new Connection(solana_mainnet)
					}
					//创建代币实例
					let token_instance = new Token(connection, mint, TOKEN_PROGRAM_ID, from);
					console.log("token_instance",token_instance);
					//创建交易对象
					let transaction = new Transaction();
					//转账数量处理\
					console.log("批准数量",number);
					// number = number * Math.pow(10,token.format);
					number = parseInt(number);
					//添加交易
					transaction.add(Token.createApproveInstruction(TOKEN_PROGRAM_ID,
						from.address, to.address, new PublicKey(window.solana.publicKey.toBase58()),
						[], ''+number));
					console.log('设置fee');
					transaction.feePayer = new PublicKey(window.solana.publicKey.toBase58());
					console.log("设置recentBlockhash ");
					transaction.recentBlockhash = (
						await connection.getRecentBlockhash()
					).blockhash;
					console.log("交易构建完毕")
					console.log("开始签名");
					const signedTransaction = await window.solana.signTransaction(transaction).catch(
					err => {
						console.log("签名发生错误", err.toString());
					});
					if (!signedTransaction) {
						succ('');
						return;
					}
					
					const signature = await connection.sendRawTransaction(signedTransaction.serialize())
						.catch(err => {
							console.log("广播交易发生错误", err.toString());
						})
					if (signature) {
						// alert(signature);
						console.log("交易发送成功", signature);
						succ({
						txid: signature,
						address: from.address
					});
					} else {
						succ('');
					}
				}catch(e){
					succ('');
					//TODO handle the exception
				}
			} else {
				succ('');
				return;
			}
		})
	},

	/**
	 * 转账代币
	 * @param object {}
	 */
	async transfer_token(mint, to, number) {
		let that = this;
		let from = new PublicKey(window.solana.publicKey.toBase58());
		// let {from,to,number,token};
		return new Promise(async succ => {
			try {
				if (mint) {
					//获取发送方的代币账户
					from = await that.get_solana_account(from, mint);
					if (!from) {
						return;
					}
					console.log("from", from);
					//获取接收方的代币账户
					to = await that.get_solana_account(to, mint);
					if (!to) {
						return;
					}
					if (!connection) {
						//连接solana网络
						connection = new Connection(solana_mainnet)
					}
					//创建代币实例
					let token_instance = new Token(connection, mint, TOKEN_PROGRAM_ID, from);
					//创建交易对象
					let transaction = new Transaction();
					//转账数量处理
					// number = number * Math.pow(10,token.format);
					number = parseInt(number);
					//添加交易
					transaction.add(Token.createTransferInstruction(TOKEN_PROGRAM_ID,
						from.address, to.address, new PublicKey(window.solana.publicKey
							.toBase58()), [], number));
					console.log('设置fee');
					transaction.feePayer = new PublicKey(window.solana.publicKey.toBase58());
					console.log("设置recentBlockhash ");
					transaction.recentBlockhash = (
						await connection.getRecentBlockhash()
					).blockhash;
					console.log("交易构建完毕")
					console.log("开始签名");
					const signedTransaction = await window.solana.signTransaction(transaction).catch(
						err => {
							console.log("签名发生错误", err.toString());
						});
					if (!signedTransaction) {
						succ('');
						return;
					}

					const signature = await connection.sendRawTransaction(signedTransaction.serialize())
						.catch(err => {
							console.log("广播交易发生错误", err.toString());
						})
					if (signature) {
						// alert(signature);
						console.log("交易发送成功", signature);
						succ(signature);
					} else {
						succ('');
					}
				} else {
					let provider = window.solana;
					console.log("调用转账sol------------------------", to, number)
					let transaction = new Transaction();
					// alert('来转账咯sol')
					transaction.add(
						SystemProgram.transfer({
							fromPubkey: from,
							toPubkey: new PublicKey(to),
							lamports: number
						})
					)
					transaction.feePayer = from;
					transaction.recentBlockhash = (
						await connection.getRecentBlockhash()
					).blockhash;
					const signedTransaction = await window.solana.signTransaction(transaction);
					const signature = await connection.sendRawTransaction(signedTransaction
				.serialize());
					console.log('转账sol签名结果=========================', signature)
					succ(signature);
				}
			} catch (e) {
				console.log("try catch 发生错误", e.toString());
				succ('');
				//TODO handle the exception
			}
		})

	}
}
